var app = require('../app');
var debug = require('debug')(app.NAME);
var _ = require('lodash');
var AV = require("leanengine");

var K = require('../common/common');
var AVUtils = require('./AVUtils');
var Response = require('./responseUtils');

var m = {
  instance: function (_request, _response, _className) {
    var restful = K.object('Restful');

    restful._pageable = function (query) {
      query.skip(_request.query._perPage * (_request.query._page - 1));
      query.limit(_request.query._perPage);
      if (_request.query._sortDir == 'DESC') {
        query.descending(_request.query._sortField);
      } else {
        query.ascending(_request.query._sortField);
      }
    };

    restful.query = function() {
      return new AV.Query(_className);
    };

    restful.class = _className;
    restful.object = function() {
      return new _className();
    };

    /**
     * 指定结果集的数量, 相同则返回 as promise, 否则 error promise.
     * @param query AVQuery
     * @param msg 数量不相等时显示的信息
     * @param count 指定数量
     * @param asParameters as promise 回调中传递的对象
     * @returns AV.Promise
     */
    restful.assertCount = function(query, msg, count, asParameters) {
      return Response.clientErrorPromise(
        Response.serverErrorPromise(query.count(), _response)
          .done(function (qcount) {
            return qcount != count ? AV.Promise.error(msg) : AV.Promise.as(asParameters);
          }), _response);
    };

    restful.assertNotCount = function(query, msg, count, asParameters) {
      return Response.clientErrorPromise(
        Response.serverErrorPromise(query.count(), _response)
          .done(function (qcount) {
            return qcount == count ? AV.Promise.error(msg) : AV.Promise.as(asParameters);
          }), _response);
    };


    restful.assertExist = function(id) {
      var query = restful.query();
      return Response.serverErrorPromise(query.get(id), _response)
        .done(function(object){
          if (! object) {
            return Response.clientError(resp, _className.k_title + '不存在');
          }
          return AV.Promise.as(object);
        }, _response);
    };

    restful.doDelete = function() {
      var avObject = AV.Object.createWithoutData(_className.k_name, _request.params.id)
      Response.serverErrorPromise(avObject.destroy(), _response)
        .done(function(){
          _response.status(200).end();
        });
    }
    restful.doGet = function(object) {
      var query = restful.query();
      Response.serverErrorPromise(query.get(_request.params.id), _response)
        .done(function(object){
          _response.json(AVUtils.toJSON(object));
        });
    };
    /*
     restful.doGet = function (relations) {
     var query = restful.query();
     Response.serverErrorPromise(query.get(_request.params.id), _response)
     .done(function (object) {
     var json = AVUtils.toJSON(object);
     var promises = [AV.Promise.as()];
     if (_.isArray(relations)) {
     for (var i in relations) {
     promises.push(Response.serverErrorPromise(object.relation(relations[i]).query().find(), _response)
     .done(function (list) {
     json[relations[i]] = [];
     for (var j in list) {
     json[relations[i]].push(list[j].id);
     //json[relations[i]].push(AVUtils.toJSON(list[j]));
     }
     }));
     }
     }
     Response.serverErrorPromise(AV.Promise.when(promises), _response)
     .done(function () {
     _response.json(json);
     });
     });
     */

    restful.doSave = function(object) {
      Response.serverErrorPromise(object.save(), _response)
        .done(function(entity) {
          _response.json(AVUtils.toJSON(entity));
        });
    };

    restful.doList = function(avObjects) {
      var query = restful.query();
      var filters = _request.query._filters;
      if (filters) {
        filters = JSON.parse(filters);
        for (var key in filters) {
          // 自定义过滤 refObject_relation_field[_refObjectFiled:defaultID]
          var splits = _.compact(key.split(/\_/));
          if (splits.length > 2) {
            if (splits[0] in avObjects) {
              var object = avObjects[splits[0]];
              var relation = splits[1];
              var field = splits[2];
              if ('in' == relation) {
                if (3 == splits.length) {
                  var ids = filters[key];
                  if (!_.isArray(ids)) {
                    ids = [ids];
                  }
                  var instances = [];
                  for (var i in ids) {
                    instances.push(AV.Object.createWithoutData(object.k_name, ids[i]));
                  }
                  query.containedIn(field, instances);
                  continue;
                }
                if (4 == splits.length) {
                  var values = filters[key];
                  if (!_.isArray(values)) {
                    values = [values];
                  }
                  var refObjectFiled = splits[3];
                  var innerQuery = new AV.Query(object);
                  innerQuery.containedIn(refObjectFiled, values);
                  query.matchesQuery(field, innerQuery);
                  continue;
                }
              }
              if ('contains' == relation) {
                if (4 == splits.length) {
                  var refObjectFiled = splits[3];
                  var innerQuery = new AV.Query(object);
                  innerQuery.contains(refObjectFiled, filters[key]);
                  query.matchesQuery(field, innerQuery);
                  continue;
                }
              }
            } else {
              debug('object "' + splits[0] + '" is not defined');
            }
          }
          if(filters[key] instanceof Array){
            if(key == "id"){
              query.containedIn("objectId", filters[key]);
              continue;
            } else {
              query.containedIn(key, filters[key]);
            }
          } else {
            query.contains(key, filters[key]);
          }
        }
      }

      Response.serverErrorPromise(query.count(), _response)
        .done(function (count) {
          _response.set('Access-Control-Expose-Headers', 'X-Total-Count');
          _response.set('X-Total-Count', count);
          restful._pageable(query);
          //query.include(Objects.Role.k_name);
          return Response.serverErrorPromise(query.find(), _response);
        })
        .done(function (results) {
          var list = [];
          for (var i in results) {
            list.push(AVUtils.toJSON(results[i]));
          }
          _response.json(list);
        });
    };

    return restful;
  }
}

module.exports = m;
